# -*- coding: utf-8 -*-

import sys, os
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import *
from PyQt4.QtCore import *

import tbgeo, tbgeoconst
from tbgeo import coordinates, position
import colors

from ui_window import Ui_MainWindow

class MyForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        self.pressed = [False, 0, 0]
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.treeWidget.sortItems(1, Qt.AscendingOrder)

        self.scene = QGraphicsScene()
        self.ui.graphicsView.setScene(self.scene)
        self.scene.mouseMoveEvent = self.mouseMoveEvent

#        self.ui.graphicsView.mouseMoveEvent = self.mouseMoveEvent1
#        self.ui.graphicsView.mousePressEvent = self.mousePressEvent
#        self.ui.graphicsView.mouseReleaseEvent = self.mouseReleaseEvent

        self.ui.graphicsView.dragMoveEvent = self.on_graphicsView_dragMoveEvent
        self.ui.graphicsView.dropEvent = self.dropEvent

        self.paths = dict()
        self.mapImage = None

    def on_treeWidget_itemDoubleClicked(self, item, column):
        if item in self.paths and not item.isDisabled():
            p = self.paths[item]
            s = p.shape()
            x = s.pointAtPercent(0)
            self.ui.graphicsView.centerOn(x)

    def on_treeWidget_itemChanged(self, item, column):
        checked = item.checkState(0) > 0

        if item.childCount() > 0:
            for i in range(item.childCount()):
                if not checked:
                    item.child(i).setCheckState(0, 0)
                else:
                    item.child(i).setCheckState(0, 2)

        elif item.parent() != None and item in self.paths:
            p = self.paths[item]
            if not checked:
                self.scene.removeItem(p)
            else:
                self.scene.addItem(p)

    def on_actionId_do_punktu_triggered(self, checked=None):
        if checked is None: return
        text, ok = QtGui.QInputDialog.getText(self, u'Idź do punktu', u'Współrzędne:')
        if not ok:
            return

        a = text.split(",")
        c = (float(a[0]), float(a[1]))
        c = coordinates(*c)
        pos = self.cal.getPosition(c)
        self.ui.graphicsView.centerOn(pos.x, pos.y)
        color = self.nextcolor()
        path = self.drawpoint(pos.x, pos.y, color)
        item = self.ui.treeWidget.topLevelItem(0)
        item.setCheckState(0, 2)
        label = "Punkty"
        it = None
        for i in range(item.childCount()):
            x = item.child(i)
            if x.text(0) == label:
                it = x
                break
        if it is None:
            it = QTreeWidgetItem(item)
            it.setText(0, label)
            it.setCheckState(0, 2)
        item = QTreeWidgetItem(it)
        item.setText(1, l)
        item.setCheckState(0, 2)
        pix = QPixmap(32, 12)
        pix.fill(color)
        item.setIcon(0, QIcon(pix))
        self.paths[item] = path

    def on_actionTrasy_triggered(self, checked=None):
        if checked is None: return
        if not checked:
            self.ui.treeWidget.setVisible(False)
        else:
            self.ui.treeWidget.setVisible(True)

    def on_actionZako_cz_triggered(self, checked=None):
        if checked is None: return
        self.close()

    def on_actionZapisz_triggered(self, checked=None):
        if checked is None: return
        try:
            self.mapImage
        except:
            pass
        fd = QFileDialog(self)
        f = fd.getSaveFileName()
        if f == "":
            return
        self.mapImage.pixmap().save(f)

    def on_actionOtw_rz_triggered(self, checked=None):
        if checked is None: return
        fd = QFileDialog(self)
        f = fd.getOpenFileName()
        if f == "":
            return
        self.draw(f)

    def on_graphicsView_dragMoveEvent(self, ev):
        if ev.mimeData().hasUrls():
            ev.acceptProposedAction()

    def dropEvent(self, ev):
        f = ev.mimeData().urls()[0].toLocalFile()
        if f.endsWith(".gpx"):
            for u in ev.mimeData().urls():
                f = u.toLocalFile()
                n = self.drawgpxpath(f)
        elif f.endsWith(".csv"):
            for u in ev.mimeData().urls():
                f = u.toLocalFile()
                n = self.drawcsvpath(f)
        else:
            self.draw(f)
#
#    def mouseReleaseEvent(self, ev):
#        self.pressed = [False, ev.x(), ev.y()]
#
#    def mousePressEvent(self, ev):
#        self.pressed = [True, ev.x(), ev.y()]
#
#    def mouseMoveEvent1(self, ev):
#        if self.pressed[0]:
#            self.ui.graphicsView.scrollContentsBy(ev.x() - self.pressed[1], ev.y() - self.pressed[2])

    def mouseMoveEvent(self, event):
        ev = event.scenePos()
        try:
            p = (int(ev.x()), int(ev.y()))
            pos = position(*p)
            c = self.cal.getCoordinates(pos)
            self.statusBar().showMessage('%4f %4f %4d %4d' % (c.lat, c.lon, ev.x(), ev.y()))
        except:
            pass

    def drawcsvpath(self, tfilename):
        f = open(tfilename, 'r')
        item = self.ui.treeWidget.topLevelItem(0)
        item.setCheckState(0, 2)
        item = QTreeWidgetItem(item)
        item.setText(0, f.name)
        item.setCheckState(0, 2)
        import os
        n = str(tfilename)
        n = os.path.split(n)[1]
        item.setText(1, n)

        path = QPainterPath()
        color = self.nextcolor()
        p = QPen(color)
        p.setWidth(2)

        import re

        pt=re.compile('[^,]+,([^,]+),([^,]+),')

        first = 1
        for line in f.readlines()[1:]:
            se=pt.search(line)
            c = float(se.group(1)), float(se.group(2))
            c = coordinates(*c)
            pos = self.cal.getPosition(c)
            pos = pos.x, pos.y
            if first:
                path.moveTo(*pos)
                first = 0
            else:
                path.lineTo(*pos)

        f.close()
        path = self.scene.addPath(path, p)
        path.setZValue(2)

        x = QTreeWidgetItem(item)
        x.setText(0, 'csv')
        self.paths[x] = path
        x.setCheckState(0, 2)

        pix = QPixmap(32, 12)
        pix.fill(color)
        x.setIcon(0, QIcon(pix))

        s = path.shape()
        rec = self.scene.sceneRect()
        q = QPainterPath()
        q.addRect(rec)
        iter = s.intersected(q)

        if iter.length() == 0:
            x.setDisabled(True)

    def drawpoint(self, x, y, color, text=None):
        path = QPainterPath()
        path.addEllipse(QPointF(x, y), 10, 10)
        path.addEllipse(QPointF(x, y), 1, 1)
        p = QPen(color)
        p.setWidth(2)
        if not text is None:
            path.addText(x + 2, y + 2, QFont('Verdana'), QString(text))
        path = self.scene.addPath(path, p)
        return path

    def nextcolor(self):
        try:
            self.curcol = (self.curcol + 1) % len(colors.coltab)
        except:
            self.curcol = 0

        return QColor(*colors.coltab[self.curcol])

    def drawgpxpath(self, tfilename):
        from xml.dom.minidom import parseString

        f = open(tfilename, 'r')
        item = self.ui.treeWidget.topLevelItem(0)
        item.setCheckState(0, 2)
        item = QTreeWidgetItem(item)
        item.setText(0, f.name)
        item.setCheckState(0, 2)
        import os
        n = str(tfilename)
        n = os.path.split(n)[1]
        item.setText(1, n)
        doc = parseString(f.read())
        f.close()

        count = 0
        for seg in doc.getElementsByTagName('trkseg'):
            count += 1
            path = QPainterPath()
            color = self.nextcolor()
            p = QPen(color)
            p.setWidth(2)
            first = 1

            x = QTreeWidgetItem(item)
            for pt in seg.getElementsByTagName('trkpt'):
                c = float(pt.getAttribute('lat')), float(pt.getAttribute('lon'))
                c = coordinates(*c)
                pos = self.cal.getPosition(c)
                pos = pos.x, pos.y
                if first:
                    path.moveTo(*pos)
                    first = 0
                else:
                    path.lineTo(*pos)

            path = self.scene.addPath(path, p)
            path.setZValue(2)

            x.setText(0, str(count))
            self.paths[x] = path
            x.setCheckState(0, 2)

            pix = QPixmap(32, 12)
            pix.fill(color)
            x.setIcon(0, QIcon(pix))

            s = path.shape()
            rec = self.scene.sceneRect()
            q = QPainterPath()
            q.addRect(rec)
            iter = s.intersected(q)

            if iter.length() == 0:
                x.setDisabled(True)

    def draw(self, tfilename):
        import tarfile
        if not tarfile.is_tarfile(tfilename):
            return

        tar = tarfile.open(tfilename, "r")
        file_list = tar.getmembers()

        filtr = filter(lambda x:x.isfile() and x.name.endswith(".map"), file_list)
        lines = tar.extractfile(filtr[0]).read().splitlines()

        map = tbgeo.Map()
        d = lines[4].split(',')[0]
        map.setDatum(d)
        p = lines[8].split(',')[1]
        map.setProjection(p)

        mmpxy = filter(lambda x:x.startswith("MMPXY"), lines)
        mmpll = filter(lambda x:x.startswith("MMPLL"), lines)

        q = zip(mmpxy, mmpll)
        maxx = 0
        maxy = 0
        for (p, c) in q:
            r1 = p.split(',')
            r2 = c.split(',')
            x = int(r1[2].strip())
            maxx = max(maxx, x)
            y = int(r1[3].strip())
            maxy = max(maxy, y)
            lon = float(r2[2].strip())
            lat = float(r2[3].strip())
            map.addCalibrationPoint(lat, lon, x, y)

        map.setWidth(maxy)
        map.setHeight(maxx)

        self.cal = tbgeo.Calibration()
        if not self.cal.register(map):
            msgBox = QMessageBox()
            msgBox.setText(self.cal.getError())
            msgBox.exec_()

        image = QImage(maxx, maxy, 4)
        paint = QPainter()
        paint.begin(image)

        import re
        p = re.compile('_([0-9]+)_([0-9]+)[^_]+$')
        list = filter(lambda x:x.isfile() and x.name.startswith("set/"), file_list)

        for l in list:
            im = QImage()
            im.loadFromData(tar.extractfile(l).read())
            im = im.convertToFormat(4)
            s=p.search(l.name)
            [x, y] = [int(s.group(1)), int(s.group(2))]
            paint.drawImage(x, y, im)

        paint.end()
        tar.close()
        self.scene.clear()
        self.scene.setSceneRect(0, 0, maxx, maxy)
        self.mapImage = self.scene.addPixmap(QPixmap.fromImage(image))
        self.mapImage.setZValue(0)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    myapp = MyForm()
    myapp.show()
    app.exec_()
    print 'ok'

#TODO:co ze sciezkami przy zmianie mapy?
#TODO:edycja trasy
#TODO:kategorie dla tras (label)
#TODO:rysowanie siatki